package org.btik.light.mobile.ui.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.*;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
import org.btik.light.mobile.R;

import java.util.Locale;

/**
 * @author lustre
 * @since 2023/4/8 1:00
 */
public class WingAngleView extends View implements View.OnTouchListener {

    private final Paint borderPaint = new Paint();//大圆的画笔

    private final Paint axisPaint = new Paint();//上下刻度

    private final Paint axisPointPaint = new Paint(); // 指针轴心

    private final TextPaint anglePaint = new TextPaint();//角度

    private final Paint anglePointPaint = new Paint();//指针
    private float radius = 220;//默认大圆的半径
    private float centerX = radius;//大圆中心点的位置cx
    private float centerY = radius;//大圆中心点的位置cy

    private float axisPointRadius;// 轴心圆的半径

    private Towards towards; //朝向 0左 右 1

    private double angle = 90; // 已选的角度

    private int angleInt = 90; // 已选的角度
    private Triangle anglePoint;
    private AngleChangeListener angleChangeListener;//移动回调的接口

    private AngleIntChangeListener angleIntChangeListener;//移动回调的接口

    private final Path triangle = new Path();

    public WingAngleView(Context context) {
        super(context);
        init(context, null);
    }

    public WingAngleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public WingAngleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    //初始化
    private void init(Context context, @Nullable AttributeSet attrs) {
        anglePoint = new Triangle();
        if (attrs != null) {
            try (TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WingAngleView)) {
                int borderColor = typedArray.getColor(R.styleable.WingAngleView_borderColor,
                        Color.GRAY);
                int axisColor = typedArray.getColor(R.styleable.WingAngleView_axisColor,
                        Color.LTGRAY);
                float axisStrokeWith = typedArray.getDimension(R.styleable.WingAngleView_axisStrokeWith,
                        6);
                radius = typedArray.getDimension(R.styleable.WingAngleView_radius, 220);
                centerY = centerX = radius;
                float angleSize = typedArray.getDimension(R.styleable.WingAngleView_angleSize, 40);
                int angleColor = typedArray.getColor(R.styleable.WingAngleView_angleColor, Color.WHITE);
                int anglePointColor = typedArray.getColor(R.styleable.WingAngleView_anglePointColor, Color.LTGRAY);
                float anglePointWith = typedArray.getDimension(R.styleable.WingAngleView_anglePointStrokeWith, 2);
                int axisPointColor = typedArray.getColor(R.styleable.WingAngleView_axisPointColor, angleColor);
                axisPointRadius = typedArray.getDimension(R.styleable.WingAngleView_axisPointRadius, 10);
                towards = Towards.values()[typedArray.getInt(R.styleable.WingAngleView_towards, 0)];

                borderPaint.setColor(borderColor);
                axisPaint.setColor(axisColor);
                axisPaint.setStrokeWidth(axisStrokeWith);
                anglePaint.setTextSize(angleSize);
                anglePaint.setTextAlign(Paint.Align.CENTER);
                anglePaint.setColor(angleColor);
                anglePointPaint.setColor(anglePointColor);
                anglePointPaint.setStrokeWidth(anglePointWith);
                axisPointPaint.setColor(axisPointColor);

            }
        }
        triangle.setFillType(Path.FillType.EVEN_ODD);
        movePoint(towards == Towards.LEFT ? centerX - radius : centerX + radius, centerY);
        setOnTouchListener(this);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(getActualSpec(widthMeasureSpec), getActualSpec(heightMeasureSpec));
    }


    //处理wrapcontent的测量
    //默认wrapcontent,大小就是 直径 则是 radius * 2
    public int getActualSpec(int spec) {
        int mode = MeasureSpec.getMode(spec);
        int len = MeasureSpec.getSize(spec);
        if (mode == MeasureSpec.AT_MOST) {
            len = (int) (radius * 2);
        }
        return MeasureSpec.makeMeasureSpec(len, mode);
    }

    //绘制
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(centerX, centerY, radius, borderPaint);
        // 画0和180 标记线
        canvas.drawLine(centerX, centerY + radius, centerX, centerY + radius - radius / 4, axisPaint);
        canvas.drawLine(centerX, centerY - radius, centerX, centerY - radius + radius / 4, axisPaint);

        // 绘制三角形
        triangle.reset();
        triangle.lineTo(anglePoint.x1, anglePoint.y1);
        triangle.lineTo(anglePoint.x2, anglePoint.y2);
        triangle.lineTo(anglePoint.x3, anglePoint.y3);
        triangle.lineTo(anglePoint.x1, anglePoint.y1);
        canvas.drawPath(triangle, anglePointPaint);
        // 绘制指针轴心
        canvas.drawCircle(centerX, centerY, axisPointRadius, axisPointPaint);
        // 绘制夹角数值
        canvas.drawText(String.format(Locale.CHINA, "%.1f", angle), centerX, centerY - radius / 3, anglePaint);

    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        float evx = event.getX(), evy = event.getY();
        float deltaX = evx - centerX, deltaY = evy - centerY;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //圆外按压不生效
                if (deltaX * deltaX + deltaY * deltaY > radius * radius) {
                    break;
                }
            case MotionEvent.ACTION_MOVE:
                movePoint(evx, evy);
                break;
        }
        return true;
    }

    /**
     * 改变位置的回调出来
     */
    private void movePoint(float fingerX, float fingerY) {
        // 控制只能转半圈
        if (towards == Towards.LEFT) {
            if (fingerX > centerX) {
                fingerX = centerX;
            }
        } else if (fingerX < centerX) {
            fingerX = centerX;
        }
        // 换算为相对圆心的坐标
        float x0 = fingerX - centerX;
        float y0 = fingerY - centerY;

        //将手指的坐标换算成固定在大圆上的点，需要根据手的滑动求出原点到手指坐标与大圆的交点
        // 圆为 x ^ 2 + y ^ 2 = r ^ 2
        // 直线为 (0 ,0 ) (x0,y0)
        // 作辅助线 x = x0 ; (0 ,0 ) (x0,y0) (x0,0)三点构成一个三角形
        // 与圆的交点为 (x1, y1) 作辅助线 x =  x1 同理构成 (0 ,0 ) (x1, y1) (x1,0) 与上述三角形属于相似三角形
        // 求出斜边长度 与 半径 r 作比例 再等比代换到  两条直角边长度得出 x1 y1
        // 求斜边

        double hypotenuse = Math.sqrt(Math.pow(x0, 2) + Math.pow(y0, 2));
        // 比值 double rate =radius/ hypotenuse;但减少先算除法带来的精度丢失 ,放到后式子先算乘法，

        float x1 = (float) (x0 * radius / hypotenuse);
        float y1 = (float) (y0 * radius / hypotenuse);

        anglePoint.x1 = x1 + centerX;
        anglePoint.y1 = y1 + centerY;
        //   1.构成指针的条件
        // 绘制指针，为一个等腰三角形，顶点为大圆上 与过原点 和 手指坐标直线交点 为上述 x1 y1
        // 两侧边以 上述 (0 ,0 ) (x1 y1) 为轴对称。且旋转时需要保持长度不变。
        // 这里取轴心圆 与 垂直于 上述轴的直线的两个交点(x2， y2) (x3, y3)。这样旋转时保存左右长度不变。

        // 2.求取底边两点的坐标
        // 作辅助线: x1 y1 与 x = x1 加 x轴 构成的三角形 与 两个上述两个交点与 x轴 以及过他们坐标垂直x轴构成的三角形为相似三角形
        // 由相似三角形 在绝对值上满足 |x2|/r0 = |y1|/r |y2|/r0 = |x1|/r ,代入 x1 y1的非绝对值 和 r r0 得出 x4 y4
        // 由于直线(x2， y2) (x3, y3)和 (0 ,0 ) (x1 y1)垂直 因而(x2， y2) (x3, y3)处于 (x1 y1)相邻象限 需要绕 x轴和y轴进行翻转
        // 这里有  x2 = x4 y2 = -y4 和 x3 = -x4 y= y4

        float x4 = y1 * axisPointRadius / radius;
        float y4 = x1 * axisPointRadius / radius;
        anglePoint.x2 = x4 + centerX;
        anglePoint.y2 = -y4 + centerY;
        anglePoint.x3 = -x4 + centerX;
        anglePoint.y3 = y4 + centerY;

        double angle = Math.abs(Math.atan2(x0, y0) * 180 / Math.PI);
        if (angle == this.angle) {
            return;
        }
        this.angle = angle;
        if (angleChangeListener != null) {
            angleChangeListener.onChange(towards == Towards.RIGHT ? 180 - angle : angle);
        }
        int angleInt = (int) angle;
        if (angleInt == this.angleInt) {
            return;
        }
        if (angleIntChangeListener != null) {
            angleIntChangeListener.onChange(towards == Towards.RIGHT ? 180 - angleInt : angleInt);
        }
        invalidate();
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
    }

    public void setAngleChangeListener(AngleChangeListener angleChangeListener) {
        this.angleChangeListener = angleChangeListener;
    }

    public void setAngleIntChangeListener(AngleIntChangeListener angleIntChangeListener) {
        this.angleIntChangeListener = angleIntChangeListener;
    }

    /**
     * 回调事件的接口
     **/
    public interface AngleChangeListener {
        void onChange(double angle);
    }

    public interface AngleIntChangeListener {
        void onChange(int angle);
    }

    static class Triangle {
        private float x1, y1, x2, y2, x3, y3;


    }

    enum Towards {
        LEFT, RIGHT
    }

}
